/*************************************************************************
 *                    free                     *
 *************************************************************************
 *************************************************************************
 * Filename	   : package_process.c
 * Description   : This file contains the processes to the packages
 * Version	   : 1.0
 * History       :
 free 2013-4-17  Create
 *************************************************************************/
#include <stdio.h>
#include "table_pat.h"
#include "table_pmt.h"
#include "package_process.h"

#define PACKAGE_SYNC_BYTE	0x47

/*************************************************************************
 * Function Name : GetPackageHeader
 * Description   : get package header information from byte array
 * Parameters    :
 *                stPackageHeader -- Pointer to strut of package header
 *                ucBuffer -- pointer to the buffer
 * Returns       :
 **************************************************************************/
void GetPackageHeader(PACKAGE_HEADER *stPackageHeader, unsigned char *pucBuffer)
{
	stPackageHeader->sync_byte = pucBuffer[0];
	stPackageHeader->transport_error_indicator = (pucBuffer[1] >> 7) & 0x01;
	stPackageHeader->payload_unit_start_indicator = (pucBuffer[1] >> 6) & 0x01;
	stPackageHeader->transport_priority = (pucBuffer[1] >> 5) & 0x01;
	stPackageHeader->PID = ((pucBuffer[1] & 0x1f) << 8) | pucBuffer[2];
	stPackageHeader->transport_scrambling_control = (pucBuffer[3] >> 6) & 0x03;
	stPackageHeader->adaptation_field_control = (pucBuffer[3] >> 4) & 0x03;
	stPackageHeader->continuity_counter = pucBuffer[3] & 0x0f;
}

/*************************************************************************
 * Function Name : CopyToFileByPID
 * Description   : copy all packages to output file whose pid matchs
 * Parameters    :
 *                pInputFile -- input file
 *                pOutputFileName -- output file name
 *                liFirstPackageOffset -- first package offset in input file
 *                iPackagePID -- user wanted pid
 * Returns       :
 **************************************************************************/
int CopyToFileByPID(FILE *pInputFile, char *pOutputFileName, int iPackageLength, long int liFirstPackageOffset, int iPackagePID)
{
	PACKAGE_HEADER stHeader = {0};
	unsigned char aucBuffer[204] = {0};
	FILE *pOutputFile = NULL;
	int iReturn = 1;

	if (0 != fseek(pInputFile, liFirstPackageOffset, SEEK_SET))
	{
		printf("input file read error!\n");
		return 0;
	}
	pOutputFile = fopen(pOutputFileName, "wb");
	if (pOutputFile == NULL )
	{
		printf("output file open error!\n");
		return 0;
	}
	while (fread(aucBuffer, sizeof(unsigned char), iPackageLength, pInputFile) == iPackageLength)
	{
		GetPackageHeader(&stHeader, aucBuffer);
		if (stHeader.PID != iPackagePID || stHeader.sync_byte != 0x47)
		{
			continue;
		}
		if (fwrite(aucBuffer, sizeof(unsigned char), iPackageLength, pOutputFile) != iPackageLength)
		{
			printf("output file write error!\n");
			iReturn = 0;
			break;
		}
	}
	fclose(pOutputFile);
	return iReturn;
}

/*************************************************************************
 * Function Name : CheckPmtMatch
 * Description   : check if the pid match the pmt wanted pid
 * Parameters    :
 *                pstTablePmt -- user wanted pmt
 *                iPackageID -- current package id
 * Returns       :1 match		0 mismatch
 **************************************************************************/
static int CheckPmtMatch(SECTION_PMT *pstTablePmt, int iPackageID)
{
	PROGRAM_ELEMENT *pstElement = NULL;
	while (pstTablePmt != NULL )
	{
		pstElement = pstTablePmt->pstProgramElements;
		while (pstElement != NULL )
		{
			if (pstElement->elementary_PID == iPackageID)
			{
				return 1;
			}
			pstElement = pstElement->pstNext;
		}
		pstTablePmt = pstTablePmt->pstNext;
	}
	return 0;
}

/*************************************************************************
 * Function Name : CopyToFileByPmt
 * Description   : copy all packages to output file whose pid matchs the pmt
 * Parameters    :
 *                pInputFile -- input file
 *                pOutputFileName -- output file name
 *                liFirstPackageOffset -- first package offset in input file
 *                pstTablePmt -- user wanted program
 * Returns       :
 **************************************************************************/
int CopyToFileByPmt(FILE *pInputFile, char *pOutputFileName, int iPackageLength, long int liFirstPackageOffset, SECTION_PMT *pstTablePmt)
{
	PACKAGE_HEADER stHeader = {0};
	unsigned char aucBuffer[204] = {0};
	FILE *pOutputFile = NULL;
	int iReturn = 1;

	if (0 != fseek(pInputFile, liFirstPackageOffset, SEEK_SET))
	{
		printf("input file read error!\n");
		return 0;
	}
	pOutputFile = fopen(pOutputFileName, "wb");
	if (pOutputFile == NULL )
	{
		printf("output file open error!\n");
		return 0;
	}
	while (fread(aucBuffer, sizeof(unsigned char), iPackageLength, pInputFile) == iPackageLength)
	{
		GetPackageHeader(&stHeader, aucBuffer);
		if (stHeader.sync_byte != PACKAGE_SYNC_BYTE)
		{
			continue;
		}
		if (!CheckPmtMatch(pstTablePmt, stHeader.PID))
		{
			continue;
		}
		if (fwrite(aucBuffer, sizeof(unsigned char), iPackageLength, pOutputFile) != iPackageLength)
		{
			printf("output file write error!\n");
			iReturn = 0;
			break;
		}
	}
	fclose(pOutputFile);
	return iReturn;
}

